using System;
using NFreeMarker.Template;
using NUnit.Framework;

// ReSharper disable InconsistentNaming
namespace NFreeMarker.Tests.Template
{
    public class TemplateTests_ProcessBuiltInsForExpertUsers
    {
        [TestFixture]
        public class When_processing_an_eval_builtin : TemplateTestsBase
        {
            [Test]
            public void Assure_the_sum_is_outputted_when_evaluating_an_add_expression()
            {
                SetTemplateContent("${value?eval}");
                AddTemplateVariable("value", "1+2");

                string output = ProcessTemplate();

                Assert.That(output, Is.EqualTo("3"));
            }
        }

        [TestFixture]
        public class When_processing_an_interpret_builtin : TemplateTestsBase
        {
            [Test]
            public void Assure_the_string_is_interpreted_as_a_callable_directive()
            {
                SetTemplateContent(
                    "<#assign inlineTemplate = '${message}'?interpret>" +
                    "<@inlineTemplate/>");
                AddTemplateVariable("message", "Hello world");

                string output = ProcessTemplate();

                Assert.That(output, Is.EqualTo("Hello world"));
            }

            [Test]
            public void Assure_the_two_element_sequence_is_interpreted_as_a_callable_directive()
            {
                SetTemplateContent(
                    "<#assign inlineTemplate = ['${message}', 'myTemplate']?interpret>" +
                    "<@inlineTemplate/>");
                AddTemplateVariable("message", "Hello world");

                string output = ProcessTemplate();

                Assert.That(output, Is.EqualTo("Hello world"));
            }
        }

        [TestFixture]
        public class When_processing_an_is_boolean_builtin : TemplateTestsBase
        {
            [Test]
            public void Assure_true_is_returned_when_the_value_is_a_boolean()
            {
                SetTemplateContent("${value?is_boolean?string}");
                AddTemplateVariable("value", true);

                string output = ProcessTemplate();

                Assert.That(output, Is.EqualTo("true"));
            }

            [Test]
            public void Assure_false_is_returned_when_the_value_is_not_a_boolean()
            {
                SetTemplateContent("${value?is_boolean?string}");
                AddTemplateVariable("value", "Hello");

                string output = ProcessTemplate();

                Assert.That(output, Is.EqualTo("false"));
            }
        }

        [TestFixture]
        public class When_processing_an_is_collection_builtin : TemplateTestsBase
        {
            [Test]
            public void Assure_true_is_returned_when_the_value_is_a_collection()
            {
                SetTemplateContent("${value?is_collection?string}");
                AddTemplateVariable("value", new SimpleCollection(new string[0]));

                string output = ProcessTemplate();

                Assert.That(output, Is.EqualTo("true"));
            }

            [Test]
            public void Assure_false_is_returned_when_the_value_is_a_sequence()
            {
                SetTemplateContent("${value?is_collection?string}");
                AddTemplateVariable("value", new SimpleSequence());

                string output = ProcessTemplate();

                Assert.That(output, Is.EqualTo("false"));
            }

            [Test]
            public void Assure_false_is_returned_when_the_value_is_not_an_enumerable()
            {
                SetTemplateContent("${value?is_collection?string}");
                AddTemplateVariable("value", "Hello");

                string output = ProcessTemplate();

                Assert.That(output, Is.EqualTo("false"));
            }
        }

        [TestFixture]
        public class When_processing_an_is_date_builtin : TemplateTestsBase
        {
            [Test]
            public void Assure_true_is_returned_when_the_value_is_a_DateTimeOffset()
            {
                SetTemplateContent("${value?is_date?string}");
                AddTemplateVariable("value", DateTimeOffset.MinValue);

                string output = ProcessTemplate();

                Assert.That(output, Is.EqualTo("true"));
            }

            [Test]
            public void Assure_true_is_returned_when_the_value_is_a_date()
            {
                SetTemplateContent("${value?date?is_date?string}");
                AddTemplateVariable("value", DateTimeOffset.MinValue);

                string output = ProcessTemplate();

                Assert.That(output, Is.EqualTo("true"));
            }

            [Test]
            public void Assure_true_is_returned_when_the_value_is_a_datetime()
            {
                SetTemplateContent("${value?datetime?is_date?string}");
                AddTemplateVariable("value", DateTimeOffset.MinValue);

                string output = ProcessTemplate();

                Assert.That(output, Is.EqualTo("true"));
            }

            [Test]
            public void Assure_true_is_returned_when_the_value_is_a_time()
            {
                SetTemplateContent("${value?time?is_date?string}");
                AddTemplateVariable("value", DateTimeOffset.MinValue);

                string output = ProcessTemplate();

                Assert.That(output, Is.EqualTo("true"));
            }

            [Test]
            public void Assure_false_is_returned_when_the_value_is_not_a_DateTimeOffset()
            {
                SetTemplateContent("${value?is_date?string}");
                AddTemplateVariable("value", "Hello");

                string output = ProcessTemplate();

                Assert.That(output, Is.EqualTo("false"));
            }
        }

        [TestFixture]
        public class When_processing_an_is_enumerable_builtin : TemplateTestsBase
        {
            [Test]
            public void Assure_true_is_returned_when_the_value_is_a_collection()
            {
                SetTemplateContent("${value?is_enumerable?string}");
                AddTemplateVariable("value", new SimpleCollection(new string[0]));

                string output = ProcessTemplate();

                Assert.That(output, Is.EqualTo("true"));
            }

            [Test]
            public void Assure_true_is_returned_when_the_value_is_a_sequence()
            {
                SetTemplateContent("${value?is_enumerable?string}");
                AddTemplateVariable("value", new SimpleSequence());

                string output = ProcessTemplate();

                Assert.That(output, Is.EqualTo("true"));
            }

            [Test]
            public void Assure_false_is_returned_when_the_value_is_not_an_enumerable()
            {
                SetTemplateContent("${value?is_enumerable?string}");
                AddTemplateVariable("value", "Hello");

                string output = ProcessTemplate();

                Assert.That(output, Is.EqualTo("false"));
            }
        }

        [TestFixture]
        public class When_processing_an_is_method_builtin : TemplateTestsBase
        {
            [Test]
            public void Assure_true_is_returned_when_the_value_is_a_method()
            {
                SetTemplateContent("${indexOf?is_method?string}");
                AddTemplateVariable("indexOf", new IndexOfMethod());

                string output = ProcessTemplate();

                Assert.That(output, Is.EqualTo("true"));
            }

            [Test]
            public void Assure_false_is_returned_when_the_value_is_not_a_method()
            {
                SetTemplateContent("${value?is_method?string}");
                AddTemplateVariable("value", "Hello");

                string output = ProcessTemplate();

                Assert.That(output, Is.EqualTo("false"));
            }
        }

        [TestFixture]
        public class When_processing_an_is_number_builtin : TemplateTestsBase
        {
            [Test]
            public void Assure_true_is_returned_when_the_value_is_a_number()
            {
                SetTemplateContent("${value?is_number?string}");
                AddTemplateVariable("value", 1);

                string output = ProcessTemplate();

                Assert.That(output, Is.EqualTo("true"));
            }

            [Test]
            public void Assure_false_is_returned_when_the_value_is_not_a_number()
            {
                SetTemplateContent("${value?is_number?string}");
                AddTemplateVariable("value", "Hello");

                string output = ProcessTemplate();

                Assert.That(output, Is.EqualTo("false"));
            }
        }

        [TestFixture]
        public class When_processing_an_is_sequence_builtin : TemplateTestsBase
        {
            [Test]
            public void Assure_false_is_returned_when_the_value_is_a_collection()
            {
                SetTemplateContent("${value?is_sequence?string}");
                AddTemplateVariable("value", new SimpleCollection(new string[0]));

                string output = ProcessTemplate();

                Assert.That(output, Is.EqualTo("false"));
            }

            [Test]
            public void Assure_true_is_returned_when_the_value_is_a_sequence()
            {
                SetTemplateContent("${value?is_sequence?string}");
                AddTemplateVariable("value", new SimpleSequence());

                string output = ProcessTemplate();

                Assert.That(output, Is.EqualTo("true"));
            }

            [Test]
            public void Assure_false_is_returned_when_the_value_is_not_an_enumerable()
            {
                SetTemplateContent("${value?is_sequence?string}");
                AddTemplateVariable("value", "Hello");

                string output = ProcessTemplate();

                Assert.That(output, Is.EqualTo("false"));
            }
        }

        [TestFixture]
        public class When_processing_an_is_string_builtin : TemplateTestsBase
        {
            [Test]
            public void Assure_true_is_returned_when_the_value_is_a_string()
            {
                SetTemplateContent("${value?is_string?string}");
                AddTemplateVariable("value", "Hello");

                string output = ProcessTemplate();

                Assert.That(output, Is.EqualTo("true"));
            }

            [Test]
            public void Assure_false_is_returned_when_the_value_is_not_a_string()
            {
                SetTemplateContent("${value?is_string?string}");
                AddTemplateVariable("value", 1);

                string output = ProcessTemplate();

                Assert.That(output, Is.EqualTo("false"));
            }
        }
    }
}
// ReSharper enable InconsistentNaming
